// the lock server implementation

#include "lock_server.h"
#include <sstream>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>

lock_server::lock_server():
  nacquire (0)
{
	pthread_mutex_init(&mutex_server, NULL);
	pthread_cond_init(&cond_server, NULL);
}

lock_server::~lock_server()
{
	pthread_mutex_destroy(&mutex_server);
	pthread_cond_destroy(&cond_server);
}

/*
clt : client id
lid : lock number
*/
lock_protocol::status
lock_server::stat(int clt, lock_protocol::lockid_t lid, int &r)
{
	lock_protocol::status ret = lock_protocol::OK;
	
	//printf("server stat clt %d, lid %ld\n", clt, lid);
	
	r = nacquire;
	return ret;
}

lock_protocol::status
lock_server::acquire(int clt, lock_protocol::lockid_t lid, int &r)
{

	lock_protocol::status ret = lock_protocol::OK;

	printf("acquire clt %d, lid %lld\n", clt, lid);

	//mutex lock
	pthread_mutex_lock(&mutex_server);

	if (map_lockState.find(lid) == map_lockState.end() || map_lockState[lid] ==  lock_server::FREE) {
		map_lockState[lid] = lock_server::LOCKED;
		printf("map lid %lld, status %d\n", lid, map_lockState.find(lid)->second);
		
	}
	else {
		/*	conditional wait.
			after this function, mutex automatically released.
			if thread gets the signal, then calls mutex_lock() to get mutex.
		*/
		while(map_lockState[lid] == lock_server::LOCKED)
			pthread_cond_wait(&cond_server, &mutex_server);
		map_lockState[lid] = lock_server::LOCKED;
	}
		

	//mutex unlock
	pthread_mutex_unlock(&mutex_server);

	r = nacquire;

	return ret;
}

lock_protocol::status
lock_server::release(int clt, lock_protocol::lockid_t lid, int &r)
{

	lock_protocol::status ret = lock_protocol::OK;


	//mutex lock
	pthread_mutex_lock(&mutex_server);
	
	if (map_lockState.find(lid) != map_lockState.end() && map_lockState[lid] == lock_server::LOCKED) {
		map_lockState[lid] = lock_server::FREE;
		pthread_cond_broadcast(&cond_server);
	}
	else {
		//invalid request
		ret = lock_protocol::NOENT;
	}
	
	//r = nacquire;
	
	//mutex unlock
	pthread_mutex_unlock(&mutex_server);


	return ret;

}

